#include "GifUtil.h"
#include "gif/cgif.h"

static uint64_t seed = 22;

namespace OCPP
{

	static int pWriteFn(void* pContext, const uint8_t* pData, const size_t numBytes) {
		StringStream* r = (StringStream*)pContext;
		if (r != nullptr) {
			r->write((const char*)pData, numBytes);
			return 0;
		}
		else {
			return -1;
		}
	}

	static int psdrand(void) {
		// simple pseudo random function from musl libc
		seed = 6364136223846793005ULL * seed + 1;
		return seed >> 33;
	}

	String GifUtil::encode(int width, int height,
		 int numFrames, 
		 int delay,
		 std::vector<Uint8Vector> frameDatas)
	{
		StringStream sstream;

		CGIFrgb_Config config = { 0 };
		CGIFrgb* pGIF;
		CGIFrgb_FrameConfig fconfig = { 0 };
		config.pWriteFn = pWriteFn;
		config.pContext = &sstream;
		config.width = width;
		config.height = height;

		pGIF = cgif_rgb_newgif(&config);         // optional: check pGIF == NULL for error handling

		std::vector<uint8_t> pImageDataRGB;
		pImageDataRGB.resize(width * height * 3);

		fconfig.pImageData = &pImageDataRGB[0];
		fconfig.fmtChan = CGIF_CHAN_FMT_RGB;  // fconfig.pImageData comes in RGB (3 byte blocks), not RGBA (4 byte blocks)
		fconfig.delay = delay;                 // set time before next frame (in units of 0.01 s)
		fconfig.attrFlags = CGIF_RGB_FRAME_ATTR_INTERLACED;


		for (int f = 0; f < numFrames; ++f) {
			for (int i = 0; i < width * height; ++i) {
				pImageDataRGB[3 * i + 0] = frameDatas[f][4 * i + 0];
				pImageDataRGB[3 * i + 1] = frameDatas[f][4 * i + 1];
				pImageDataRGB[3 * i + 2] = frameDatas[f][4 * i + 2];
			}
			cgif_rgb_addframe(pGIF, &fconfig);     // add next frame (colors are approximated if there are more than 256 different colors in the frame)
		}
		cgif_result r = cgif_rgb_close(pGIF);    // optional: r can be used for error handling

		return sstream.str();
	}
}